Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ISEA Inverse projection (#3047) #4211

Merged
merged 4 commits into from
Aug 14, 2024
Merged

ISEA Inverse projection (#3047) #4211

merged 4 commits into from
Aug 14, 2024

Conversation

jerstlouis
Copy link
Contributor

@jerstlouis jerstlouis commented Jul 31, 2024

@jerstlouis
Copy link
Contributor Author

jerstlouis commented Jul 31, 2024

@rouault @MichaelJendryke @ppKrauss @ldesousa would you be able to help test / validate? Thanks!

@jerstlouis jerstlouis force-pushed the master branch 5 times, most recently from e734459 to f6805d9 Compare August 1, 2024 03:07
@jerstlouis
Copy link
Contributor Author

jerstlouis commented Aug 1, 2024

This inverse implementation is now working (successful latlon==>ISEA==>latlon roundtrip) now assuming the parameters:

+proj=isea +R=6371007.18091875.

For +orient=pole, it would just be a matter of using the polarISEA object instead of standardISEA (I am not sure how to detect that parameter).

For other values of +R / ellipsoid etc., I don't know if it's just a matter of multiplying xy.x and xy.y by a member of the PJ *P argument instead of by earthAuthalicRadius?

For the +mode other than plane, is it possible to simply not support these for the inverse?

Will different values of +x_0, +y_0, +lat_0, +lon_0 be handled automatically by code outside isea.cpp?

Not sure about supporting the other parameters.

I've clarified that our (provisionary) OGC:1534 CRS is equivalent to:

+proj=pipeline
   +step +proj=geoc
   +step +proj=isea +R=6371007.18091875 +x_0=19186144.8709401525557041 +y_0=-3323137.7717845365405083 

which implies a geodetic->geocentric conversion that does not get performed automatically by +isea.
From past experiments, this conversion was required to align with data registered to an ISEA3H DGGS.

Not sure whether this should automatically be done by +proj=isea?

For the ISEA 5x6 space (provisionally called OGC:153456) used to define the ISEA9R 2D Tile Matrix Set (where 10/30 level 0 tiles are valid -- could also define an ISEA4R quad-tree 2DTMS), which is also a convenient space for doing ISEA3H calculations, we can simply add an affine transform:

+proj=pipeline
   +step +proj=geoc
   +step +proj=isea +R=6371007.18091875 +x_0=19186144.8709401525557041 +y_0=-3323137.7717845365405083
   +step +proj=affine +inv
      +s11=3837228.9741880306974053 +s12=3837228.9741880302317441
      +s21=6646275.5435690730810165 +s22=-6646275.543569073081016

In the 5x6 space, the twelve icosahedron vertices are very conveniently/intuitively at:

  • 1,0 (same as 2,1; 3,2; 4,3; 5,4) "top" of unfolded icosahedron -- corresponding to applied orientation: 58.454376167463 N, 11.25 E for standard +orient=isea
  • 0,2 (same as 1,3; 2,4; 3,5; 4,6) "bottom" of unfolded icosahedron -- 58.454376167463 S, 168.75 W for +orient=isea
  • 0,0 (same as 5,5) -- left vertex
  • 1,1 -- first top dent
  • 2,2 -- second top dent
  • 3,3 -- third top dent
  • 4,4 -- fourth top dent
  • 0, 1 (same as 5, 6) -- right vertex
  • 1,2 -- first bottom dent
  • 2,3 -- second bottom dent
  • 3,4 -- third bottom dent
  • 4,5 -- fourth bottom dent

and these points are all on the equator:

  • 0, 1 (same as 5, 6) -- right vertex
  • 1, 1.5
  • 2, 2 -- second top dent vertex
  • 3, 3 -- third top dent vertex
  • 3.5, 4
  • 4, 5 -- fourth bottom dent vertex

cc. @allixender @perrypeterson @mpadillaruiz

@jerstlouis
Copy link
Contributor Author

For the appveyor MSVC failure, maybe we need to add #include <algorithm>:

https://stackoverflow.com/questions/19439670/min-max-not-a-member-of-std-errors-when-building-opencv-2-4-6-on-windows-8

@jerstlouis
Copy link
Contributor Author

jerstlouis commented Aug 1, 2024

The need for the pipeline to do the correct geodetic->geocentric conversion is problematic with e.g., gdalwarp:

gdalwarp  ~/Desktop/gebco.tiff test.tiff -s_srs "EPSG:4326" -t_srs "+proj=pipeline +step +proj=geoc +step +proj=isea +R=6371007.18091875 +x_0=19186144.8709401525557041 +y_0=-3323137.7717845365405083"
ERROR 1: PROJ: proj_crs_get_coordinate_system: Object is not a SingleCRS
ERROR 1: PROJ: proj_crs_get_coordinate_system: Object is not a SingleCRS
Using band 4 of destination image as alpha.
Using band 4 of source image as alpha.
Warning 1: The definition of geographic CRS EPSG:4326 got from GeoTIFF keys is not the same as the one from the EPSG registry, which may cause issues during reprojection operations. Set GTIFF_SRS_SOURCE configuration option to EPSG to use official parameters (overriding the ones from GeoTIFF keys), or to GEOKEYS to use custom values from GeoTIFF keys and drop the EPSG code.
ERROR 1: PROJ: proj_crs_get_coordinate_system: Object is not a SingleCRS
ERROR 1: PROJ: proj_crs_get_coordinate_system: Object is not a SingleCRS
ERROR 1: PROJ: proj_crs_get_datum: Object is not a SingleCRS
ERROR 1: PROJ: proj_crs_get_datum_ensemble: Object is not a SingleCRS
ERROR 1: PROJ: proj_crs_get_coordinate_system: Object is not a SingleCRS
ERROR 1: PROJ: proj_create_operations: target_crs is not a CRS or a CoordinateMetadata
ERROR 6: Cannot find coordinate operations from `EPSG:4326' to `{
  "$schema": "https://proj.org/schemas/v0.7/projjson.schema.json",
  "type": "Conversion",
  "name": "PROJ-based coordinate operation",
  "method": {
    "name": "PROJ-based operation method: +proj=pipeline +step +proj=geoc +step +proj=isea +R=6371007.18091875 +x_0=19186144.8709401525557041 +y_0=-3323137.7717845365405083 +type=crs"
  },
  "parameters": []
}'

whereas this kindof works now (complained about missing inverse before):

gdalwarp  ~/Desktop/gebco.tiff test.tiff -s_srs "EPSG:4326" -t_srs "+proj=isea +R=6371007.18091875 +x_0=19186144.8709401525557041 +y_0=-3323137.7717845365405083"
Using band 4 of destination image as alpha.
Using band 4 of source image as alpha.
Warning 1: The definition of geographic CRS EPSG:4326 got from GeoTIFF keys is not the same as the one from the EPSG registry, which may cause issues during reprojection operations. Set GTIFF_SRS_SOURCE configuration option to EPSG to use official parameters (overriding the ones from GeoTIFF keys), or to GEOKEYS to use custom values from GeoTIFF keys and drop the EPSG code.
Processing /home/jerome/Desktop/gebco.tiff [1/1] : 0...10...20...30...40...50...60...70...80...90...100 - done.

except for some missing bits at the extremities:

gdalWarpedToISEA

@jerstlouis
Copy link
Contributor Author

jerstlouis commented Aug 6, 2024

@rouault This inverse seems to be working quite well. This is the sample GeoJSON file I mentioned in #3047 inverse-projected to EPSG:4326 in QGIS by doing a Set Layer CRS to:

+proj=isea +R=6371007.18091875 +x_0=19186144.8709401525557041 +y_0=-3323137.7717845365405083

qgisInverseISEA

(together with a Natural Earth countries layer in EPSG:4326).

Or de-projecting countries of the whole world in ISEA projection:

https://maps.gnosis.earth/ogcapi/collections/NaturalEarth:cultural:ne_10m_admin_0_countries/items.geojson?limit=1000&crs=OGC:1534

countriesISEA

Here's how a full ISEA GEBCO raster (https://maps.gnosis.earth/ogcapi/collections/gebco/map.tiff?crs=OGC:1534) deprojects in QGIS (just a few minor glitches around the interruptions):

GEBOUnprojected

Should I file a separate issue about whether +proj=isea should actually be doing the +proj=geoc step automatically?

I believe that the correct ISEA projection actually implies that step, and just as mentioned in OSGeo/gdal#10537, it will still not be possible to accurately visualize things since the +proj=pipeline cannot be used with Set Layer CRS etc.

cc. @ppKrauss @mpadillaruiz @ldesousa @perrypeterson @allixender

@rouault
Copy link
Member

rouault commented Aug 7, 2024

Should I file a separate issue about whether +proj=isea should actually be doing the +proj=geoc step automatically?

no idea. What does the literature about this projection says about that? But the fact that you define a spherical ellipsoid with +R=6371007.18091875 and you mention the authalic radius makes me think that perhaps you would need to use the +R_A switch instead (https://proj.org/en/9.4/usage/ellipsoids.html#ellipsoid-spherification-parameters instead), which is sometimes used for a number of projection methods

@jerstlouis
Copy link
Contributor Author

jerstlouis commented Aug 8, 2024

Thanks for triggering the builds @rouault .

The compilation warning as errors settings are a bit over the top... Any chance for some help addressing or bypassing those issues, or is there otherwise an easy way to test this locally? cmake / make / make test all work perfectly fine on my Linux system (g++ (GCC) 14.1.1 20240720), but I don't get those warnings as errors on what seems to be the compilers' opinionated idea of proper C++ style (not being able to trigger the CI builds myself doesn't help either).

Is there a particular set of GCC flags that will likely results in all builds passing if I manage to compile locally with them?

What does the literature about this projection says about that?

As far as I know the official ISEA paper is the Snyder1992 paper.

But this paper may actually be describing multiple projections as @ldesousa mentioned, and it definitely mentions multiple polyhedrons such as the truncated icosahedron for example, whereas ISEA is really about the icosahedron base solid (Figure 12, though that does not show the standard ISEA orientation but the +orient=pole one).
I could never really understand that paper, despite several attempts at reading it, because it's all over the place with these different solids, and how it talks about hexagonal faces where the ISEA projection itself has nothing to do with hexagons, and then later on page 16 Application to the Platonic Polyhedral Globes describes this can be simplified ignoring hexagons for the platonic solids.

The term geodetic or geocentric do not appear, and the word latitude appears on page 14 and 20 only, and the letter ϕ. and lat is used and "geographic laititude" is used which would make you think it it is talking about geodetic latitude.
However, conceptually it is a spherical Earth with the surface area of the ellipsoid which is mapped to the icosahedron, so converting to geocentric first would make sense.

The main reason I've started to think this geodetic ==> geocentric step was necessary is because it was needed to correctly integrate data served by PYXIS / uCalgary using their PYX0 format, for things to align properly in our visualization client. We mention this in the FMSDI Phase 3 ER.

I am hoping that experts on the topic (@sahrk @franz-benjamin @shatzi @perrypeterson @mpadillaruiz @ldesousa @allixender) could chime in, so that we could clarify whether the geocentric conversion is implied or not. Essentially we need an agreement on what the ISEA projection really is. This is why a new issue might be a better place for this discussion than this pull request or the original missing inverse issue...

But the fact that you define a spherical ellipsoid with +R=6371007.18091875 and you mention the authalic radius makes me think that perhaps you would need to use the +R_A switch instead (https://proj.org/en/9.4/usage/ellipsoids.html#ellipsoid-spherification-parameters instead), which is sometimes used for a number of projection methods

I did try the +R_A switch, but I was repeatedly/continuously mixing it up with +R_a.

The 6371007.18091875 is calculated as:

#define wgs84InvFlattening 298.257223563
#define wgs84Major         6378137.0
#define wgs84Minor         (wgs84Major - (wgs84Major / wgs84InvFlattening)) // 6356752.3142451792955399
#define a2                 (wgs84Major * wgs84Major)
#define c2                 (wgs84Minor * wgs84Minor)
#define eccentricity       0.0818191908426 // sqrt(1.0 - (c2/a2));
#define log1pe_1me         0.1640050079196   // log((1+e)/(1-e)))
#define S                  (Pi * (2 * a2 + c2/eccentricity * log1pe_1me))
#define earthAuthalicRadius 6371007.18091875 //sqrt(S / (4 * Pi)); // R -- authalic sphere radius for WGS84 [6371007.1809184747 m]

This also matches the numbers here -- √(510 065 621.724 km2 / (4 * π)) =
6 371 007.1809 m

The documentation is a bit confusing, compounded by the fact that both R_a and R_A exist and are completely different things.

+R_A: A sphere with the same surface area as the ellipsoid.

I imagine this ellipsoid defaults to GRS80? So if I want to use an authalic sphere with the same surface area as WGS84, would I say +ellps=WGS84 +R_A?
Then that should be exactly the same as +R=6371007.18091875? The results are the same (when not confusing case-sensitive +R_a with +R_A as I must have done several times):

echo -168.7500000     58.2825256 | proj +proj=isea +R=6371007.18091875
-19186144.87	3323137.77

echo -168.7500000     58.2825256 | proj +proj=isea +ellps=WGS84 +R_A
-19186144.87	3323137.77

Omitting the +ellps=WGS84 yields the same results up to three decimals, likely because WGS84 and GRS80 differ so slightly...

However, I still get a small difference between the +R=6371007.18091875 vs. +ellps=WGS84 +R_A:

echo -168.7500000     58.2825256 | proj +proj=isea +ellps=WGS84 +R_A -f "%.10f"
-19186144.8722200952	3323137.7725913548

echo -168.7500000     58.2825256 | proj +proj=isea +R=6371007.18091875 -f "%.10f"
-19186144.8717271797	3323137.7725059795

Possibly related discussion by other confused users.

Does any of this have any relation to the extra +proj=geoc step?

Thanks!

@sahrk
Copy link

sahrk commented Aug 8, 2024

As far as I know the official ISEA paper is the Snyder1992 paper.

But this paper may actually be describing multiple projections as @ldesousa mentioned,

Snyder's paper gives projections for multiple polyhedra using the same approach. For convenience we named his icosahedral projection "ISEA".

The term geodetic or geocentric do not appear, and the word latitude appears on page 14 and 20 only, and the letter ϕ. and lat is used and "geographic laititude" is used which would make you think it it is talking about geodetic latitude. However, conceptually it is a spherical Earth with the surface area of the ellipsoid which is mapped to the icosahedron, so converting to geocentric first would make sense.

The ISEA projection is defined on the sphere. On the sphere there is no distinction between geodetic and geocentric latitudes; they are always equal. If you're integrating data defined on an ellipsoid then some sort of conversion will be necessary.

Note that we chose the authalic radius for the ISEA3H DGGS so that authalic latitude could be used to define equal area cells on the ellipsoid. I believe any other conversion approach results in cells on the ellipsoid which are not equal area.

ISEA is really about the icosahedron base solid (Figure 12, though that does not show the standard ISEA orientation but the +orient=pole one).

I don't think Snyder specified a "standard" orientation for his projection. Like the acronym ISEA, the orientation we chose for ISEA-based DGGS was something we came up with later.

it talks about hexagonal faces where the ISEA projection itself has nothing to do with hexagons

He's referring to the hexagonal faces of a truncated icosahedron, which is one of the polyhedra he defines his projection on. This is unrelated to the hexagonal cells of a DGGS.

@ldesousa
Copy link
Contributor

ldesousa commented Aug 8, 2024

@jerstlouis This is a commendable effort, glad that you took upon it. I can't test it right now, but will keep an eye on this PR.

The projection we call "Snyder Equal-area" is actually defined for a right triangle on the spherical surface. It can be used to project a sphere into any polyhedron whose faces can be decomposed into right triangles. Snyder himself was primarily concerned with the Dodecahedron (his favourite), the Icosahedron and the truncated Icosahedron, but the same formulation should apply beyond those.

Neither John Snyder, nor those who followed immediately on his steps towards DGGS (White, Kimmerling, etc), defined a "standard" or "default" orientation of the polyhedra. Concerning the Icosahedron, those articles from the early 90s debate to some extent the "inconvenience" of an icosahedron positioned with vertices on the poles always having at least one other vertex on land.

In conclusion: the orientation of the polyhedron should be a parameter to any implementation of Snyder's Equal-area projection. That could be the position of a vertex plus an azimuth to a proximate (adjacent?) vertex. That's what @sahrk did in dggrid.

@jerstlouis
Copy link
Contributor Author

jerstlouis commented Aug 8, 2024

@sahrk Thank you very much for the clarifications!

The ISEA projection is defined on the sphere. On the sphere there is no distinction between geodetic and geocentric latitudes; they are always equal.

I guess this means that +proj=isea should not do this +proj=geoc step automatically, but it should also generally not be used without a perfectly spherical ellipsoid.

Note that we chose the authalic radius for the ISEA3H DGGS so that authalic latitude could be used to define equal area cells on the ellipsoid. I believe any other conversion approach results in cells on the ellipsoid which are not equal area.

Assuming that this authalic latitude conversion is not already done by the ISEA projection in PROJ and geogrid, then I suspect that our implementation of the ISEAH grid as well the PYXIS implementation we tested with in the FMSDI might not be the true ISEA3H DGGS, since we seemed to be using the geocentric latitude rather than the authalic latitude. @perrypeterson @shatzi Any insights / evidence of the contrary about that would be very useful.

The zones are clearly not perfectly equal area as computed on the WGS84 ellipsoid (though within the 1% margin allowed by Topic 21 v2 "Equal Area") as can be seen here.

I am curious about whether geogrid is actually using the geodetic latitude for its DGGS, or converting from/to geocentric or authalic elsewhere in the code? I could not find anywhere in the code where this is done. @franz-benjamin Any insight on that would be very useful.

So ideally this OGC:1534 CRS which we want to define for the purpose of facilitating the implementation of ISEA DGGs should probably imply this geodetic ==> authalic latitude conversion before applying the ISEA projection (rather than geodetic ==> geocentric).

That currently seems even more difficult to do with PROJ, since that is not one of the conversions already supported by the pipelines.

@sahrk Does this sound like a reasonable assessment?

In order to achieve interoperability between multiple implementations of ISEA DGGs, we need clarity on how to bring in and take out georeferenced information correctly, including how geodetic latitude is mapped to the ISEA sphere prior to mapping to the icosahedron. Right now it seems like different implementations of ISEA3H are using three different types of latitudes: geodetic (geogrid), geocentric (PYXIS & GNOSIS), and authalic (DGGRID).

NOTE: GDGGS03 does not mention authalic latitudes.

@ldesousa

In conclusion: the orientation of the polyhedron should be a parameter to any implementation of Snyder's Equal-area projection. That could be the position of a vertex plus an azimuth to a proximate (adjacent?) vertex

Currently, PROJ supports +orient=pole and +orient=isea (the standard ISEA orientation for DGGs), as well as an arbitrary azimuth parameter.

This implementation of the inverse supports both of these orientations (and could easily support additional ones), but does not yet support the azimuth parameter.

I'm also just realizing that we may need an additional parameter reflecting this azimuth for describing the orientation of polyhedron-based DGGs in the draft DGGRS definition -- e.g., to support the R. Buckminster Fuller's Dymaxion Orientation.

Thanks all!

@sahrk
Copy link

sahrk commented Aug 9, 2024

@sahrk Thank you very much for the clarifications!

@jerstlouis you're welcome!

The ISEA projection is defined on the sphere. On the sphere there is no distinction between geodetic and geocentric latitudes; they are always equal.

I guess this means that +proj=isea should not do this +proj=geoc step automatically, but it should also generally not be used without a perfectly spherical ellipsoid.

The ISEA projection as defined by Snyder and implemented in DGGRID is a spherical projection only. So that sounds logical to me.

Note that we chose the authalic radius for the ISEA3H DGGS so that authalic latitude could be used to define equal area cells on the ellipsoid. I believe any other conversion approach results in cells on the ellipsoid which are not equal area.

Assuming that this authalic latitude conversion is not already done by the ISEA projection in PROJ and geogrid, then I suspect that our implementation of the ISEAH grid as well the PYXIS implementation we tested with in the FMSDI might not be the true ISEA3H DGGS, since we seemed to be using the geocentric latitude rather than the authalic latitude. @perrypeterson @shatzi Any insights / evidence of the contrary about that would be very useful.

The zones are clearly not perfectly equal area as computed on the WGS84 ellipsoid (though within the 1% margin allowed by Topic 21 v2 "Equal Area") as can be seen here.

I got a 503 error from your data server, but one caveat on cell area variance: if you’re calculating the area on the earth’s surface by treating the edges as great circle arcs then you’re not going to get the exact correct area for an ISEA cell, even on the sphere.

So ideally this OGC:1534 CRS which we want to define for the purpose of facilitating the implementation of ISEA DGGs should probably imply this geodetic ==> authalic latitude conversion before applying the ISEA projection (rather than geodetic ==> geocentric).
That currently seems even more difficult to do with PROJ, since that is not one of the conversions already supported by the pipelines.

@sahrk Does this sound like a reasonable assessment?

If you want an ellipsoidal datum and you want equal area cells then I think that’s your only choice.

btw I’m not a fan of “zones” for cells. It minimizes the important (if so far unrealized) use cases where cell indexes indicate points, rather than areal zones.

In order to achieve interoperability between multiple implementations of ISEA DGGs, we need clarity on how to bring in and take out georeferenced information correctly, including how geodetic latitude is mapped to the ISEA sphere prior to mapping to the icosahedron. Right now it seems like different implementations of ISEA3H are using three different types of latitudes: geodetic (geogrid), geocentric (PYXIS & GNOSIS), and authalic (DGGRID).

I’ll give you a fourth. Probably the most widely disseminated and used dataset on an ISEA grid is the ESA’s SMOS soil moisture products. They wanted 15km cell node spacing, so chose an ISEA4H resolution 9. They also needed it on the WGS84 ellipsoid. So they just took the spherical latitudes produced by DGGRID and treated them as WGS84 ellipsoid latitudes. At a resolution of 15km the error is too small to worry about; it may even be below the representational precision. I’ve referred to that faux ellipsoidal projection as “ISEL”.

NOTE: GDGGS03 does not mention authalic latitudes.

I don’t think it mentions ellipsoids/spheres at all; that was beyond the scope of the paper. But DGGRID, which was essentially companion software for that paper, has always used the authalic radius.

@jerstlouis
Copy link
Contributor Author

jerstlouis commented Aug 9, 2024

@sahrk

I got a 503 error from your data server

Sorry, the server seems to be prone to these since this week's last update, and we're currently struggling to figure out the cause. I restarted it so hopefully you can try it again before it goes down. Trying to fix these ASAP.

but one caveat on cell area variance: if you’re calculating the area on the earth’s surface by treating the edges as great circle arcs then you’re not going to get the exact correct area for an ISEA cell, even on the sphere.

We are not doing that -- we're using several points along the edges and de-projecting each of these to calculate this accurately. Here's a sample image of what that looks like for level 0 zones and the same info as a table below (in summary, compared to the mean zone area (Earth surface area / 12 zones), the 4 polar (Earth geographic poles) level 0 zones have 0.2% smaller areas, whereas the 4 equatorial level 0 zones have 0.17% larger areas, while the remaining 4 zones have 0.03% larger areas):

ZoneArea

Level 0 Zones
(variance relative to 42,505,468.48 km² reference mean zone surface area)

Zone ID Area Variance Min Lat Min Lon Max Lat Max Lon
A0-0-A 42,420,592.22 km² -0.2 % 21.0337617856831 101.2500000030306 90 -78.7500000030306
A0-0-B 42,420,594.2 km² -0.2 % 21.0337617833224 -135.8114780636077 90 158.558247808623
A1-0-A 42,577,990.62 km² +0.17 % -35.4460114254118 -168.7500000000045 35.446011427561 -99.6551574473396
A2-0-A 42,517,825.61 km² +0.03 % 0.0000000009586 -123.7499999994206 69.2228046463321 -33.7500000009366
A3-0-A 42,517,826.83 km² +0.03 % -69.2228046463321 -123.7499999990634 0.0000000010893 -33.7499999994906
A4-0-A 42,577,985.62 km² +0.17 % -35.446011425382 -57.8448425514859 35.4460114254118 11.2500000000041
A5-0-A 42,420,594.2 km² -0.2 % -90 -78.7499999969695 -21.0337617833224 101.2499999969694
A6-0-A 42,577,985.62 km² +0.17 % -35.446011425382 11.2499999999959 35.4460114254118 80.3448425514859
A7-0-A 42,517,827.45 km² +0.03 % -69.2228046463321 56.2499999994905 0.0000000010894 146.2499999990634
A8-0-A 42,517,825.61 km² +0.03 % 0.0000000009586 56.2500000009365 69.2228046463321 146.2499999994207
A9-0-A 42,577,988.65 km² +0.17 % -35.4460114254118 122.1551574473396 35.446011427561 -168.7499999999959
A9-0-C 42,420,588.11 km² -0.2 % -90 43.9418186867605 -21.0337617833225 -21.6866565645132

Total surface area: 510,065,624.74 km²

btw I’m not a fan of “zones” for cells. It minimizes the important (if so far unrealized) use cases where cell indexes indicate points, rather than areal zones.

I am really happy you bring this up! We had some recent discussion for DGGS-JSON where I was advocating for a representedValue member that could indicate whether the sampled values best represents the zone area, the centroid or a vertex (a particular vertex to be defined -- not an easy task for ISEA3H). There was a lot of pushback to allow anything except zone area, but I believe there are some important, if less popular, use cases for points (which I think is what you're pointing out), including for example storing/transporting data registered to an ISEA3H even level zone using dual ISEA9R grids, where an area of ISEA3H corresponds to a vertex in ISEA9R (as we were doing in experiments with PYXIS for the FMSDI pilot project). I would really love to hear more about other use cases for representing points (but we're probably already getting quite off-topic).

As for the term "zone", itself, the two terms are defined as such in OGC Topic 21:

4.2. cell spatial, spatio-temporal or temporal unit of geometry with dimension greater than 0, associated with a zone (Clause 4.52)
4.52. zone particular region of space-time

So in both cases, they seem to imply this areal meaning.
Another reason we're avoiding cell in OGC API - DGGS is because of the potential confusion with a gridded coverage cell, and the possibility to retrieve coverage data for a particular zone, where the gridded coverage cells may not necessarily match DGGS zones at all.

So they just took the spherical latitudes produced by DGGRID and treated them as WGS84 ellipsoid latitudes.

Wouldn't that be the same as the first geodetic latitude case I mention that I believe geogrid may be using?
i.e., importing data registered to a WGS84 ellipsoid by taking the WGS84 latitudes and using that directly as the spherical latitude mapped to the icosahedron.

But DGGRID, which was essentially companion software for that paper, has always used the authalic radius.

Using a sphere with a radius of 6 371 007.1809 m corresonding to √(510 065 621.724 km2 / (4 * π)) (the surface area of the WGS84 ellipsoid) is one thing, which we're doing in both GNOSIS and PYXIS, and which can be specified to PROJ with +R=6371007.18091875.

But using a preliminary conversion of geodetic ==> authalic latitude is a completely different thing, isn't it? i.e., when integrating data referenced to the WGS84 ellipsoid, applying this step to convert geodetic latitude to latitude on the sphere mapped to the icosahedron:

authlat1
where
authlat2
and
authlat3

as described at https://en.wikipedia.org/wiki/Latitude#Authalic_latitude .

This is how I understand what you mean by:

so that authalic latitude could be used to define equal area cells on the ellipsoid. I believe any other conversion approach results in cells on the ellipsoid which are not equal area.

If you want an ellipsoidal datum and you want equal area cells then I think that’s your only choice.

Which would result in the only area discrepency (as computed on the WGS84 ellipsoid) being the pentagonal zones having 5/6th the area of the hexagonal zones.
Is that correct, and what DGGRID is doing?

Thanks again so much, your input is invaluable to getting this all right and achieving our goals of DGGS interoperability.

@sahrk
Copy link

sahrk commented Aug 9, 2024

@sahrk

We are not doing that -- we're using several points along the edges and de-projecting each of these to calculate this accurately.

@jerstlouis That’s all I was getting at. As long as you’ve densified the edges in ISEA space and verified the area is stable you should be fine.

btw I’m not a fan of “zones” for cells. It minimizes the important (if so far unrealized) use cases where cell indexes indicate points, rather than areal zones.

I am really happy you bring this up! We had some recent discussion for DGGS-JSON… would really love to hear more about other use cases for representing points (but we're probably already getting quite off-topic).

This is a deep topic beyond our scope here. I suggest reading the discussion on using DGGS to represent DGGS cell geometries (including vertices) in Sahr 2019, in particular the section entitled “EXACT REPRESENTATION AND SUBSTRATE GRIDS”.

Using cells to represent “vector” points can be applied to any vector use case, not just the representation of cell vertices. The last time I looked at the OGC standard it appeared to me that you were claiming to solve the problem of unifying raster/vector datasets by rasterizing the vector datasets, which is not a solution to the problem at all. But we are indeed off topic…

As for the term "zone", itself, the two terms are defined as such in OGC Topic 21:

4.2. cell spatial, spatio-temporal or temporal unit of geometry with dimension greater than 0, associated with a zone (Clause 4.52)
4.52. zone particular region of space-time

That looks to me like you’re doubling down on DGGS cell/zone indicating an areal unit only.

So in both cases, they seem to imply this areal meaning. Another reason we're avoiding cell in OGC API - DGGS is because of the potential confusion with a gridded coverage cell, and the possibility to retrieve coverage data for a particular zone, where the gridded coverage cells may not necessarily match DGGS zones at all.

I don’t know enough about OGC terminology to know what your definition of “gridded coverage cell” is. Just taking the words as english I would say that DGGS units are “gridded coverage cells”.

So they just took the spherical latitudes produced by DGGRID and treated them as WGS84 ellipsoid latitudes.

Wouldn't that be the same as the first geodetic latitude case I mention that I believe geogrid may be using? i.e., importing data registered to a WGS84 ellipsoid by taking the WGS84 latitudes and using that directly as the spherical latitude mapped to the icosahedron.

Could be. I don’t think geodetic latitude is defined the same on a sphere and an ellipse, but I’m not a geodesist.

But DGGRID, which was essentially companion software for that paper, has always used the authalic radius.

But using a preliminary conversion of geodetic ==> authalic latitude is a completely different thing, isn't it?

I’m not sure what point you’re trying to make. Why would we use the authalic radius otherwise? DGGRID does not currently support an ellipsoid model, but implementing the authalic conversion has been on my todo list since the beginning.

But we’re getting off topic here….

This is how I understand what you mean by:

so that authalic latitude could be used to define equal area cells on the ellipsoid. I believe any other conversion approach results in cells on the ellipsoid which are not equal area.

If you want an ellipsoidal datum and you want equal area cells then I think that’s your only choice.

Which would result in the only area discrepency being the pentagonal zones having 5/6th the area of the hexagonal zones. Is that correct?

I believe so, yes.

@jerstlouis
Copy link
Contributor Author

jerstlouis commented Aug 9, 2024

Thanks again @sahrk .

The last time I looked at the OGC standard it appeared to me that you were claiming to solve the problem of unifying raster/vector datasets by rasterizing the vector datasets, which is not a solution to the problem at all.

That is one approach (which is what the DGGS-JSON representation does for example), which I would have thought offers some partial solution to the problem, if not an ideal / perfect solution. There are other approaches, possibly better suited for vector data, such as clipping vector geometry to a particular areal zone (and generalizing the geometry with a minimum distance treshold between points based on that zone's resolution), or expressing the geometry vertices as zone IDs representing their centroids. I'll have to read your 2019 paper -- thanks!

That looks to me like you’re doubling down on DGGS cell/zone indicating an areal unit only.

That's how the terms are specified in Topic 21 definitions, so I'm not really "doubling down", but at least for OGC standards we have to try to align with that terminology. I think addressing the use cases of representing / addressing "points" is a different topic, regardless of the terminology used.

Just taking the words as english I would say that DGGS units are “gridded coverage cells”.

I believe that OGC "gridded coverage" as defined by Topic 6 (e.g., see 5.3.2 Grid on page 11-12) implies a rectilinear grid, which DGGS units are not necessarily. So for gridded coverage cells, although the cells themselves are not necessarily shaped in a particular way, they are at least organized in a rectilinear grid. e.g., the rectilinear pixels/gridded coverage cells in this PNG zone data response:

https://maps.gnosis.earth/ogcapi/collections/gebco/dggs/ISEA3H/zones/A6-0-E/data.png
zoneData

do not correspond to finer zones/cells of ISEA3H (this output is in EPSG:4326, but it would also apply to an ISEA projection output CRS). I can see however how the definition of "Grid" in Topic 6 could be extended to be more flexible so that most DGGs could potentially qualify.

Whereas for a DGGS-JSON representation of the same zone data, individual values for sub-zones correspond to finer hexagonal zones (as visualized above).

I’m not sure what point you’re trying to make. Why would we use the authalic radius otherwise?

I actually always wondered about that!!! :) Since it seems that we've been doing data integration from WGS84-referenced data in GNOSIS and PYXIS without using authalic latitudes. Now I understand the purpose of that authalic radius because of that authalic latitude concept, and I'll have a go at implementings this WGS84 geodetic latitude => authalic latitude conversion.

@sahrk
Copy link

sahrk commented Aug 9, 2024

@jerstlouis I fear we've hijacked this pull request but just wanted to add one more thing that might interest you...

There are other approaches, possibly better suited for vector data, such as ,,, expressing the geometry vertices as zone IDs representing their centroids.

This is the basic way to encode vector locations. This approach encodes the location at a single precision, and then (possibly) indexes that encoding using a hierarchical indexing. That is the best that is possible using systems like H3 or A3HT. But some hierarchical indexing systems allow for multi-precision quantization. See Sahr 2013 or the corresponding slide deck.

@jerstlouis
Copy link
Contributor Author

jerstlouis commented Aug 12, 2024

@rouault

Sorry for diverging into the above long parenthesis in this PR, but the discussions were highly insightful and did address the questions I had. To recap and summarize and try to move this forward:

  1. Is there a set of compiler flags I can pass GCC to test compilation locally that will help me address the CI build failures (to turn on all these warnings / warnings as errors)?
  2. The ISEA projection is only defined on the sphere, therefore it does not make sense to use it with a non-spherical ellipsoid. I don't know if some kind of warning would be appropriate when trying to use it with a non-spherical ellipsoid?
  3. The correct preliminary step for going from WGS84 to ISEA would be to use geodetic ==> authalic latitude -- not geocentric as we have been doing in GNOSIS and I believe PYXIS as well. This is the purpose of using an authalic radius for ISEA discrete global grids, and would result in truly equal area zones for zones of the same shape (e.g., ISEA3H hexagons). Does PROJ provide this geodetic ==> authalic latitude conversion capability?
  4. I'm curious about the small difference between +R=6371007.18091875 vs. +ellps=WGS84 +R_A, which I would have understood to be fully equivalent
echo -168.7500000     58.2825256 | proj +proj=isea +ellps=WGS84 +R_A -f "%.10f"
-19186144.8722200952	3323137.7725913548
echo -168.7500000     58.2825256 | proj +proj=isea +R=6371007.18091875 -f "%.10f"
-19186144.8717271797	3323137.7725059795

Thanks!

@jerstlouis
Copy link
Contributor Author

jerstlouis commented Aug 13, 2024

with a longer explanation later in the page about the restrictions on which forms of isea are supported in the inverse direction.

As far as I understand, what is not currently supported is the +azi=<value>, +aperture=<value>, +resolution=<value> and +mode=<string>.

However, there are no tests for any of these even for the forward projection, which at least in TDD practice would imply they do not work :)

I question whether +aperture, +resolution and +mode should be included at all in this projection. I have no idea what di or dd mean, and I have no idea what hex implies (and the documentation does not say anything about it), and I have been working heavily with ISEA for the last 3 years. At first glance, these parameters seem to be mixing up the concept of discrete global grids with the concept of the underlying projection.

Actually, there is one test expecting a failure:

operation +proj=isea   +mode=hex +resolution=31
accept  0 0
expect  failure

I imagine it's testing a resolution too high?

@rouault
Copy link
Member

rouault commented Aug 13, 2024

I question whether +aperture, +resolution and +mode should be included at all in this projection. I have no idea what di or dd mean, and I have no idea what hex implies

me neither. So perhaps just mentions that the inverse direction is only available when none of those options is specified?

I imagine it's testing a resolution too high?

yes, this just tests we don't run into undefined behavior found by a fuzzer which generates "random" PROJ strings, and was fixed per 4c8a5cb

@jerstlouis
Copy link
Contributor Author

jerstlouis commented Aug 13, 2024

Snyder's Icosahedral Equal Area map projection on polyhedral globes for the dodecahedron and truncated icosahedron

This is actually confusing and probably wrong. The ISEA projection is strictly on the icosahedron.

As discussed above, the paper confusingly talks about several different projections on different solids, but ISEA is specifically about the icosahedron. The original code had some hints that the author wanted to implement different solids, but only the icosahedron is implemented.

and for certain instructional tools and databases, the projections are useful for world maps.

This does not read well at all to me, and the description says nothing about the discrete global grids that this projection is widely used for.

I'm proposing to change the description to:

Snyder's Icosahedral Equal Area map projections on an icosahedron polyhedral globe
offers relatively low scale and angular distortion. The equations involved are
relatively straight-forward. The interruptions remain a disadvantage, as with
any low-error projection system applied to the entire globe :cite:Snyder1992.
This projection is used as a basis for defining discrete global grid hierarchies.

and add this note regarding the use of ellipsoids:

.. note:: As the projection is only defined on a sphere, it should only be used
with a spherical ellipsoid e.g., +R=6371007.18091875 for a sphere with the
authalic radius of the WGS84 ellipsoid. For mapping coordinates on the WGS84
ellipsoid to the authalic sphere, the input latitude should be converted
from geodetic latitude to authalic latitude. A future version may automatically
perform this conversion when using a non-spherical ellipsoid.

@jerstlouis jerstlouis force-pushed the master branch 6 times, most recently from ab841ac to e66e3b0 Compare August 13, 2024 20:57
- Integrating code ported from Java to eC, then eC to C++ implementing the inverse ISEA projection
- Originally from Franz-Benjamin Mocnik's ISEA implementation found at
   https://github.com/mocnik-science/geogrid/blob/master/src/main/java/org/giscience/utils/geogrid/projections/ISEAProjection.java
   (MIT License)
- NOTE: The inverse only supports the default planar options
- Eliminating several redundant trigonometric function calls
- Single shared definition of dodecahedron vertices
  (centers of icosahedral triangular faces) for
  forward and inverse
- Shared data structure for forward and inverse
- Consistent use of 0-base index for triangular faces
@jerstlouis
Copy link
Contributor Author

What is this trescale? Does this correspond to an undocumented +rescale= parameter?

    if (pj_param(P->ctx, P->params, "trescale").i) {
        Q->radius = ISEA_SCALE;
    }

How do these s, t, r parameter prefixes work e.g., sorient, tazi, razi?

- NOTE: There may have been an undocumented +rescale= parameter which
will no longer work
@rouault
Copy link
Member

rouault commented Aug 14, 2024

How do these s, t, r parameter prefixes work e.g., sorient, tazi, razi?

cf https://github.com/OSGeo/PROJ/blob/master/src/param.cpp#L112

@jerstlouis
Copy link
Contributor Author

jerstlouis commented Aug 14, 2024

The isea_disn() I removed in last commit was not reachable (like several other enum values in isea_address_form, nothing would set output to ISEA_SEQNUM).

That serial seems very much like an 64-bit integer zone index, similar to the ones we define for the ISEA9R DGGRS.

Those dd, di and hex modes, and those related aperture, resolution parameters, isea_ptdd(), isea_dddi_ap3odd(), isea_dddi(), isea_ptdi(), isea_hex() really all seem related to particular discrete global grids / zone identifier reference systems that can be built on top of the ISEA planar projection.

The isea_ptdd() is eerily familiar, looking very much like the 60 deg rotated / 30 deg horizontally sheared 5x6 ISEA space I was talking about above:

convert projected triangle coords to quad xy coords, return quad number

    isea_rotate(pt, downtri ? 240.0 : 60.0);
    if (downtri) {
        pt->x += 0.5;
        pt->y += cos30;
    }

which can be achieved with an affine transform:

+proj=pipeline
   +step +proj=isea +R=6371007.18091875 +x_0=19186144.8709 +y_0=-3323137.7718
   +step +proj=affine +inv +s11=3837228.97419 +s12=3837228.97419 +s21=6646275.54357 +s22=-6646275.54357

Does all this really belong in PROJ? It seems like all that code belongs in discrete global grid reference system libraries like geogrid and DGGRID, not in a projection library.

With the exception of what isea_tri_plane() is doing, all of those extra modes perform additional operations on top of what the default planar mode does.

This isea_tri_plane() is doing a simple translation plus a 180 degrees rotation, which should really be optimized because it makes no sense to make 4 trigonometric calls to rotate a point by 180 degrees.

None of this is tested, and none of it is documented properly. Would there be any way to know if anyone is using these things, and if so, could we suggest to move this code to a separate module that can build on top of the default plane mode?

(Does PROJ have a deprecation mechanism?)

@rouault
Copy link
Member

rouault commented Aug 14, 2024

Would there be any way to know if anyone is using these things

Ask first on https://lists.osgeo.org/mailman/listinfo/proj , which I assume will be met with silence :-), and then remove them and wait for a few months to see if people complain when the new PROJ version hits them. In any case, that should be done in a separate pull request

(Does PROJ have a deprecation mechanism?)

We don't really have a runtime warning level. If we wanted to do a stage deprecation, perhaps the isea.rst page should be updated to mention that parameters X, Y, Z will be removed in PROJ 9.6

Besides that, is there anything left for this PR? It looks good to me as it

@jerstlouis
Copy link
Contributor Author

In any case, that should be done in a separate pull request

Are you OK with the undocumented rescale parameter removed in the last commit?
I believe that's the only reachable functionality that is removed.

I did separate commits in case you wanted to pick and choose what to merge. Feel free to squash them if you prefer.

If we wanted to do a stage deprecation, perhaps the isea.rst page should be updated to mention that parameters X, Y, Z will be removed in PROJ 9.6

That would be a good idea. Would you want to do this separately and/or after asking on the mailing list?

Besides that, is there anything left for this PR? It looks good to me as it

Just let me fix this isea_rotate(pt, 180.0); right now -- other than that it should be all good.

@rouault
Copy link
Member

rouault commented Aug 14, 2024

I did separate commits in case you wanted to pick and choose what to merge

separate (clean) commits is fine

That would be a good idea. Would you want to do this separately and/or after asking on the mailing list?

I would (let you) asking on the mailing list first, and in the absence of negative feedback, proceed to update the doc

- Avoid calling isea_rotate() in isea_tri_plane() to rotate
  coordinates in bottom triangles by 180 degrees.
@jerstlouis
Copy link
Contributor Author

I would (let you) asking on the mailing list first, and in the absence of negative feedback, proceed to update the doc

Thanks, will do.

I just tried adding tests for +orient=pole and one test case is failing (it might be an issue with the forward projection). Looking into it.

@rouault
Copy link
Member

rouault commented Aug 14, 2024

I just tried adding tests for +orient=pole and one test case is failing (it might be an issue with the forward projection). Looking into it.

I would appreciate if we could merge quickly this PR. Currently I need to click on a button in github UI each time you update the PR, so that github actions are run, because, as you don't have any commit merged yet into this repository, github doesn't trust you yet...

@jerstlouis
Copy link
Contributor Author

I would appreciate if we could merge quickly this PR.

Sorry to be spamming PR updates.
If you prefer to merge this one now, I could open a separate PR for that +orient=pole fix.

@rouault rouault added this to the 9.5.0 milestone Aug 14, 2024
@rouault rouault merged commit af475c6 into OSGeo:master Aug 14, 2024
22 of 23 checks passed
@rouault
Copy link
Member

rouault commented Aug 14, 2024

I've just merged this PR.

jerstlouis added a commit to jerstlouis/ogcapi-discrete-global-grid-systems that referenced this pull request Aug 14, 2024
- Additional `azimuth` parameter for polyhedron orientation which is necessary
  to place the second vertex e.g., for R. Buckminster Fuller's Dymaxion Orientation
  ( see https://webpages.sou.edu/~sahrk/dgg/orientation/dymorient.html ).
  Latitude and Longitude of first vertex is not enough.
- Clarify that to reference spatial information to the DGGRS, geodetic latitudes
  on the WGS84 ellipsoid must go through a geodetic latitude ==> authalic latitude
  conversion ( see https://en.wikipedia.org/wiki/Latitude#Authalic_latitude )
  to map them to the authalic sphere.
- See related discussions in OSGeo/PROJ#4211
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ISEA: inverse projection method is not implemented
5 participants